/*****************************************************************
 MYD Engine v0.1

 File: myd_sprite.cpp
 Created: 26/06/06
*****************************************************************/

#include "myd_sprite.h"
#include "graphics/myd_renderer.h"
#include "graphics/myd_texture.h"

using namespace myd;

Sprite::Sprite()
:
Entity(),
currentAnim(new Animation()),
animParser(new Parser()),
count(0)
{
	// set the vertex values
	TextureVertex* pkV = &(vertices[0]);
	pkV->X = -0.5f;	pkV->Y = -0.5f;	pkV->Z = 1.0f;
	pkV->U = 0.0f;	pkV->V = 1.0f;
	
	pkV = &(vertices[1]);
	pkV->X = -0.5f;	pkV->Y = 0.5f;	pkV->Z = 1.0f;
	pkV->U = 0.0f;	pkV->V = 0.0f;

	pkV = &(vertices[2]);
	pkV->X = 0.5f;	pkV->Y = -0.5f;	pkV->Z = 1.0f;
	pkV->U = 1.0f;	pkV->V = 1.0f;

	pkV = &(vertices[3]);
	pkV->X = 0.5f;	pkV->Y = 0.5f;	pkV->Z = 1.0f;
	pkV->U = 1.0f;	pkV->V = 0.0f;
}

void Sprite::clone(Sprite& tm_Sprite)
{
	// check for clone to self
	if(&tm_Sprite == this)
		return;

	// increment smart pointers references
	tm_Sprite.wn_Texture = wn_Texture;

	// copy vertices
	for(unsigned int i=0; i<4; i++)
		tm_Sprite.vertices[i] = vertices[i];
}

void Sprite::draw(Renderer &tm_Renderer) const
{
	assert(wn_Texture);

	Entity::draw(tm_Renderer);
	
	if(tm_Renderer.bindTexture(*wn_Texture))
		tm_Renderer.draw(vertices, Renderer::TRIANGLE_STRIP, 4);
	else
		assert(0);
}

void Sprite::update(float fTimeBetweenFrames)
{
	Entity::update(fTimeBetweenFrames);

	// update the animations
	if (currentAnim->isPlaying){
		count += fTimeBetweenFrames;

		Frame fInfo = currentAnim->getFrameInfo(currentAnim->calculateFrame(count));
		
		setTextureArea(fInfo.frOffsetX, fInfo.frOffsetY, fInfo.frWidth, fInfo.frHeight);
	}
}

void Sprite::setTextureArea(unsigned int uiOffsetX, 
							unsigned int uiOffsetY, 
							unsigned int uiWidth, 
							unsigned int uiHeight)
{
	assert(wn_Texture);

	float fTexWidth = static_cast<float>(wn_Texture->getWidth());
	float fTexHeight = static_cast<float>(wn_Texture->getHeight());
	
	// calculate the texture coordinates
	float fU1 = uiOffsetX / fTexWidth;
	float fU2 = (uiOffsetX + uiWidth) / fTexWidth;

	float fV1 = uiOffsetY / fTexHeight;
	float fV2 = (uiOffsetY + uiHeight) / fTexHeight;

	// update the vertices
	TextureVertex* pkV = &(vertices[0]);
	pkV->U = fU1;	pkV->V = fV2;
	
	pkV = &(vertices[1]);
	pkV->U = fU1;	pkV->V = fV1;

	pkV = &(vertices[2]);
	pkV->U = fU2;	pkV->V = fV2;

	pkV = &(vertices[3]);
	pkV->U = fU2;	pkV->V = fV1;
}

void Sprite::setAnimation(char* defFileName, bool tm_looped)
{
	animParser->readFile(defFileName);

	//int frameCount;
	int frameCount = atoi(animParser->readVector[0][0].c_str());
	float speed = atoi(animParser->readVector[0][1].c_str());

	currentAnim->setParameters(speed, frameCount, tm_looped);

	for(int i=1;i<frameCount+1;i++)
		currentAnim->addFrame(atoi(animParser->readVector[i][0].c_str()),
							  atoi(animParser->readVector[i][1].c_str()),
							  atoi(animParser->readVector[i][2].c_str()),
							  atoi(animParser->readVector[i][3].c_str()));
}
